#define number_of_words 4000000
#define fscanf ignoreVariable = fscanf
#define number_of_articles 820000


int ignoreVariable;
int maksWord = 0;

struct vectorInt
{
    int len ;
    int last;
    int* table;
}
;

struct vectorShort
{
    int len ;
    int last;
    short* table;
}
;

struct vectorFloat
{
    int len;
    int last;
    float * table;
}
;

typedef struct vectorInt vectorInt;
typedef struct vectorShort vectorShort;
typedef struct vectorFloat vectorFloat;

int poczatek = 0;

vectorInt vec_article[number_of_words];  //= malloc( sizeof(vectorInt) );
vectorShort vec_position[number_of_words]; //= malloc( number_of_words * sizeof(vectorInt));
vectorFloat vec_float[number_of_words];
int lenOfArticles[ number_of_articles];

int  vec_last_article[number_of_words];  //= malloc( number_of_words * sizeof(int));
float normOfArticles[number_of_articles];

int size = 0;

void _indeks_start()
{
    int i;
    for(i = 0 ; i < number_of_words; i++)
        vec_last_article[i] = 0;
}

void appendInt(vectorInt* v, int number)
{

        if( v->last >= v->len )
        {
            printf("l74\n");
            exit(1);
        }
        v->table[v->last] = number;
        v->last++;
}


int _start_structure()
{
    int i;
    int lenArticle = 0 ;
    int lenPosition = 0 ;
    int wskaznikArticle = 0;
    int wskaznikPosition = 0;


    for(i = 0; i < number_of_words ; i ++)
    {
        if( vec_last_article[i] != 0 )
        {
            lenArticle += vec_article[i].len;
            lenPosition += vec_position[i].len;
        }
    }
    int * tableOfArticles = malloc(lenArticle * sizeof(int) );
    short * tableOfPosition = malloc(lenPosition * sizeof(short) );
    float * tableOfFloat = malloc( lenArticle * sizeof(float) );


    int k;
    for( k = 0; k < lenArticle ; k ++ )
    {
                tableOfArticles[k] = 0;
    }

    for( k = 0; k < lenPosition ; k ++ )
    {
                tableOfPosition[k] = 0;
    }

    for(i = 0; i < number_of_words ; i ++)
    {
        if( vec_last_article[i] != 0 )
        {
            vec_article[i].table = tableOfArticles + wskaznikArticle;
            vec_position[i].table = tableOfPosition + wskaznikPosition;
            vec_float[i].table = tableOfFloat + wskaznikArticle;
            wskaznikArticle += vec_article[i].len;
            wskaznikPosition += vec_position[i].len;
            vec_last_article[i] = -1;
            vec_article[i].last = 0;
            vec_position[i].last = 0;
            vec_float[i].last = 0;
        }

    }
    return 0;
}


int end(vectorInt *v)
{
    return v->table[v->last - 1];
}


void appendShort(vectorShort* v, int number)
{
        if( v->last >= v->len )
        {
            printf("l74\n");
            exit(1);
        }

        v->table[v->last] = number;
        v->last++;
}


int _indeks_put(int word, int article, int position)
{
    if( position > 32000)
    {
        position = 32000;
    }

    lenOfArticles[article] += 1;
    
    if( article == 0)
    {
        printf("l78 -artykul musi byc wiekszy od zera!\n");
        exit(1);

    }
    if( word <= 0)
    {
        printf("l84 - slowo musi miec numer wiekszy od zera!\n");
        exit(1);

    }
    if(  vec_last_article[word] == 0 )
    {
        printf("%d %d %d %d %d\n",word,vec_article[word].last,vec_article[word].len,vec_position[word].last,vec_position[word].len);
        printf("l111\n");
        exit(1);
    }

    if( vec_last_article[word] == article )
    {
        appendShort(&vec_position[word],position);
    }
    else
    {
        appendInt(&vec_article[word],article);
        appendShort(&vec_position[word],-position);
        vec_last_article[word] = article;
    }
    return 0;
}


void _indeks_serialize(char* fileName)
{
    int i;
    printf("maks word to %d\n",maksWord);
    FILE * out = fopen(fileName,"w");
    for(i = 0 ; i < number_of_words ; i ++)
    {
        if( vec_last_article[i] != 0 )
        {
            fprintf(out,"%d\n",vec_article[i].len);
            fprintf(out,"%d\n",vec_position[i].len);
        }
        else
        {
            fprintf(out,"%d\n",-1);
            fprintf(out,"%d\n",-1);
        }
    }
    fclose(out);
}


void _fully_indeks_serialize(char *fileName)
{
    int i;
    FILE * out = fopen(fileName,"w");
    for(i = 0 ; i < number_of_articles ; i ++)
    {
        fprintf( out,"%d\n", lenOfArticles[i] );
    }
    for(i = 0 ; i < number_of_words ; i ++)
    {
        if( vec_last_article[i] != 0 )
        {
            fprintf(out,"%d\n",vec_article[i].len);
            fprintf(out,"%d\n",vec_position[i].len);
        }
        else
        {
            fprintf(out,"%d\n",-1);
            fprintf(out,"%d\n",-1);
        }
    }
    int k;
    for(i = 0 ; i < number_of_words ; i ++)
    {
        if( vec_last_article[i] != 0 )
        {
            for(k = 0 ; k < vec_article[i].len ; k ++)
            {
                fprintf(out,"%d\n",vec_article[i].table[k]);
            }
            for(k = 0 ; k < vec_position[i].len ; k ++)
            {
                fprintf(out,"%d\n",vec_position[i].table[k]);
            }
        }

    }
    fclose(out);
}

void _fully_indeks_deserialize(char* fileName)
{
    int i;
    FILE * out = fopen(fileName,"r");
    if( !out )
    {
        printf("indeks.c: l262. Plik do deserializacji nie istnieje!\n");
    }
    for(i = 0 ; i < number_of_articles ; i ++)
    {
        int temp;
        fscanf( out,"%d\n", &temp );
        lenOfArticles[i] = temp;
    }
    for(i = 0 ; i < number_of_words ; i ++)
    {
        int temp;
        fscanf(out,"%d\n",&temp);
        if( temp != -1 )
        {
            vec_article[i].len = temp;
            vec_float[i].len = temp;
            (fscanf(out,"%d\n",&temp));
            vec_position[i].len = temp;
            vec_last_article[i] = 1;

        }
        else
        {
            (fscanf(out,"%d\n",&temp));
            vec_article[i].len = 0;
            vec_position[i].len = 0;
            vec_last_article[i] = 0;
        }
    }

    printf("init ok\n");
    _start_structure();
    printf("start structure ok\n");
    for(i = 0 ; i < number_of_words ; i ++)
    {

        if( vec_last_article[i] != 0 )
        {
            int temp;
            int k;
            for(k = 0 ; k < vec_article[i].len ; k ++)
            {
                fscanf(out,"%d\n",&temp);
                vec_article[i].table[k] = temp;
            }
            for(k = 0 ; k < vec_position[i].len ; k ++)
            {
                fscanf(out,"%d\n",&temp);
                vec_position[i].table[k] = temp;
            }
        }
    }
    printf("read ok\n");
    
    for(i = 0 ; i < number_of_words ; i ++)
    {
        if( vec_last_article[i] != 0 )
        {
            int k = -1;
            int l = 0;

            while( k < vec_article[i].len )
            {
                if( vec_position[i].table[l] < 0 )
                {
                    if( vec_position[i].table[l] == -1 ){
                        k++;
                        l++;
                        vec_float[i].table[k] = 4 * lenOfArticles[ vec_article[i].table[k] ] ;
                    }
                    else
                    {
                        k++;
                        l++;
                        vec_float[i].table[k] =  1.;
                    }
                }
                else
                {
                    if( vec_position[i].table[l] == 1 ){
                        l++;
                        vec_float[i].table[k] += 4 * lenOfArticles[ vec_article[i].table[k] ] ;
                    }
                    else
                    {
                        l++;
                        vec_float[i].table[k] +=  1.;
                    }                
               }
            }
        }
    }
    printf("stage 1 ok\n");
    for(i = 0 ; i < number_of_words ; i ++)
    {
        if( vec_last_article[i] != 0 )
        {
            int k;
            for(k = 0; k < vec_article[i].len; k ++)
            {
                vec_float[i].table[k] /= log( (double) vec_article[i].len + 2 );
                vec_float[i].table[k] /= log( (double) vec_article[i].len + 2 );
                if( vec_article[i].table[k] >= number_of_articles)
                {
                    printf("l324: %d \n", vec_article[i].table[k]);
                    exit(1);
                }
                normOfArticles[ vec_article[i].table[k] ] += vec_float[i].table[k] * vec_float[i].table[k];
            }
        }
    }
    for(i = 0 ; i < number_of_articles ; i ++)
    {
        normOfArticles[i] = sqrt( normOfArticles[i] );
    }

    printf("stage 2 ok\n");
    
    for(i = 0 ; i < number_of_words ; i ++)
    {
        if( vec_last_article[i] != 0 )
        {    
            int k;
            for(k = 0; k < vec_article[i].len; k ++)
            {
                vec_float[i].table[k] /= normOfArticles[ vec_article[i].table[k] ];
            }
       }
    }
    printf("stage 3 ok\n");
    fclose(out);
}


void _indeks_deserialize(char * fileName)
{
    int i;
    FILE * in = fopen(fileName,"r");
    if( ! in )
    {
        printf("index.c: l324. Plik %s nie istnieje!\n",fileName);
        exit(1);
    }
    for(i = 0 ; i < number_of_words ; i ++)
    {
        int temp;
        fscanf(in,"%d\n",&temp);
        if( temp != -1 )
        {
            vec_article[i].len = temp;
            fscanf(in,"%d\n",&temp);
            vec_position[i].len = temp;
            vec_last_article[i] = 1;

        }
        else
        {
            fscanf(in,"%d\n",&temp);
            vec_article[i].len = 0;
            vec_position[i].len = 0;
            vec_last_article[i] = 0;
        }
    }
    /*
    if( vec_last_article[1] == 0)
    {
        printf("l142 \n");
        exit(1);
    }
    */
    fclose(in);
}

int _mock_put(int word, int article, int position)
{
    if( word > maksWord )
    {
        maksWord = word;
    }
    if( article == 0)
    {
        printf("l338 -artykul musi byc wiekszy od zera!\n");
        exit(1);

    }
    if( word <= 0)
    {
        printf("%d %d\n",word,word+700000);
        printf("l344 - slowo musi miec numer wiekszy od zera!\n");
        exit(1);

    }
    if( poczatek == 0)
    {
        poczatek = 1;
        _indeks_start();
    }
    if( word >= number_of_words - 10)
    {
        printf("l355 - za duza wartosc slowa!\n");
        exit(1);

    }

    if( vec_last_article[word] == 0 )
    {
           vec_article[word].len = 1;
           vec_position[word].len = 1;
           vec_last_article[word] = article;

    }
    else if( vec_last_article[word] == article )
    {
           vec_position[word].len += 1;
    }
    else
    {
        vec_article[word].len += 1;
        vec_position[word].len += 1;
        vec_last_article[word] = article;
    }
    return 0;
}
